package com.pocket.demo.core.i18n;

import com.google.common.base.Strings;
import com.pocket.demo.base.api.PageResult;
import com.pocket.demo.base.api.R;
import com.pocket.demo.base.enums.MsgCodeEnum;
import com.pocket.demo.base.exception.BusinessException;
import com.pocket.demo.base.utils.LocaleContextUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.NoSuchMessageException;
import org.springframework.stereotype.Component;

import java.util.Locale;

/**
 * 处理信息国际化 【demo-i18n-2.2】
 **/
@Component("messageSourceService")
public class MessageSourceService implements MessageSourceAware {

    private static final Logger logger = LoggerFactory.getLogger(MessageSourceService.class);
    private static MessageSource messageSource;

    @Override
    public void setMessageSource(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    public MessageSource getMessageSource() {
        return this.messageSource;
    }

    /**
     * 成功响应，无返回数据
     * @return
     */
    public static R getOkResult() {
        return getRestResult(MsgCodeEnum.SUCCESS);
    }

    /**
     * 成功响应，带返回数据
     * @return
     */
    public <T> R<T> getOkResult(T data) {
        return getRestResult(MsgCodeEnum.SUCCESS, data, new Object[0]);
    }

    /**
     * 失败响应。获取 rest 返回结果，不带数据
     * @param msgCode
     * @param args
     * @return
     */
    public static R<Object> getRestResult(MsgCodeEnum msgCode, Object... args){
        return R.fail(msgCode.getCode(), msgCode.getMsgKey(), getMessage(msgCode, args));
    }

    /**
     * 获取 rest 返回结果，带数据
     * @param msgCodeEnum
     * @param data
     * @param args
     * @return
     * @param <T>
     */
    public <T> R<T> getRestResult(MsgCodeEnum msgCodeEnum, T data, Object... args) {
        if (data instanceof PageResult){
            PageResult pageDto = (PageResult) data;
            return (R<T>) R.success(msgCodeEnum.getCode(), getMessage(msgCodeEnum, new Object[0]), pageDto.getData(), pageDto);
        }
        return R.success(msgCodeEnum.getCode(), getMessage(msgCodeEnum), data);
    }

    public String getMessage(String msgKey) {
        if (Strings.isNullOrEmpty(msgKey)) {
            return "";
        }
        return this.messageSource.getMessage(msgKey, null, null, LocaleContextUtil.getLocale());
    }

    public String getMessage(String msgKey, Object... args) {
        if (Strings.isNullOrEmpty(msgKey)) {
            return "";
        }
        return this.messageSource.getMessage(msgKey, args, null, LocaleContextUtil.getLocale());
    }

    public String getMessage(Locale locale, String msgKey, Object... args) {
        if (Strings.isNullOrEmpty(msgKey)) {
            return "";
        }
        return this.messageSource.getMessage(msgKey, args, null, locale);
    }

    public static String getMessage(MsgCodeEnum msgCodeEnum, Object... args) {
        String msg;
        try {
            switch (msgCodeEnum) {
                case SUCCESS:
                case ERROR:
                    msg = msgCodeEnum.getMsgKey();
                    return msg;
            }
            msg = messageSource.getMessage(msgCodeEnum.getMsgKey(), args, LocaleContextUtil.getLocale());
        } catch (NoSuchMessageException e) {
            logger.error(e.getMessage(), e);
            msg = msgCodeEnum.getMsgKey();
        }
        return msg;
    }


    public R getResultFromBusinessException(BusinessException e) {
        R result = getRestResult(e.getMsgCodeEnum(), e.getArgs());
        result.setDebug(e.getDebug());
        if (e.getFromException() != null) {
            R from = getResultFromBusinessException(e.getFromException());
            result.setMsg(result.getMsg() + " " + from.getMsg());
        }
        return result;
    }

    public String getExceptionMessage(Exception e) {
        if (e instanceof BusinessException) {
            BusinessException b = (BusinessException)e;
            return getTextDetails(b.getMessage(), b.getArgs());
        }
        return e.getMessage();
    }

    /**
     * 根据错误标识<msgKey>获取国际化提示语
     * @param msgKey
     * @param args
     * @return
     */
    public String getTextDetails(String msgKey, Object... args) {
        String msg;
        try {
            msg = this.messageSource.getMessage(msgKey, args, LocaleContextUtil.getLocale());
        } catch (NoSuchMessageException e) {
            logger.error(e.getMessage(), e);
            msg = msgKey;
        }
        return msg;
    }

}
